出处:掘金

原作者:金泽宸


为什么要手写 new

面试中经常问:

理解 new 的本质,才能真正理解:

new 做了哪些事?

const obj = new Foo(arg1, arg2);

等价于:

  1. 创建一个空对象 obj
  2. 将该对象的 __proto__ 指向 Foo.prototype
  3. this 绑定为该对象并执行 Foo 函数
  4. 如果构造函数 return 一个对象类型,则 new 表达式的结果就是这个对象,否则返回步骤 1 创建的对象

手写 new

function myNew(Constructor, ...args) {
  // 1. 创建一个空对象,设置原型指向构造函数的 prototype
  const obj = Object.create(Constructor.prototype);

  // 2. 执行构造函数,将 this 指向这个新对象
  const result = Constructor.apply(obj, args);

  // 3. 返回结果:如果构造函数返回的是对象,则返回该对象,否则返回 obj
  return (typeof result === 'object' && result !== null) || typeof result === 'function'
    ? result
    : obj;
}

用例验证

function Person(name, age) {
  this.name = name;
  this.age = age;
}
const p = myNew(Person, '小明', 18);
console.log(p.name); // 小明
console.log(p.__proto__ === Person.prototype); // true


// 特殊情况验证
function Animal() {
  return { type: 'cat' };
}
const a = myNew(Animal);
console.log(a.type); // cat

常见易错点

错误点 正确处理
忘记绑定原型 Object.create(Constructor.prototype)
忘记处理返回对象的情况 判断 return 是否为对象/函数
Object.setPrototypeOf 不建议直接用,面试常让用 Object.create

扩展问题